﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using SCRUM.Core.DAO;
using SCRUM.Core.BusinessObjects;
using System.Collections.Specialized;

/// <summary>
/// Widget displays all Sprints, User stories, Backlog items and Tasks in tree like structure.
/// User may browse the hierarchy and display all subentities for choosen entity, return to parent entity
/// and perform create, update, delete operations on all of the entities while his role is Scrum master or Porduct owner.
/// Standard team member has only read access.
/// </summary>
public partial class TreeView2Widget : WidgetBase
{
    /// <summary>
    /// Gets title from resources
    /// </summary>
    public override string Title
    {
        get { return (string)GetLocalResourceObject("Title"); }
    }

    /// <summary>
    /// Widget editable property
    /// </summary>
    public override bool IsEditable
    {
        get { return false; }
    }

    /// <summary>
    /// Gets the name of the widget. It must be exactly the same as the folder that contains the widget.
    /// </summary>
    /// <value>Name of the widget</value>
    public override string Name
    {
        get { return "TreeView2Widget"; }
    }

    /// <summary>
    /// This method works as a substitute for Page_Load. You should use this method for
    /// data binding etc. instead of Page_Load.
    /// </summary>
    public override void LoadWidget()
    {
        Releases.DataSource = DAORelease.GetAllReleases();
        Releases.DataBind();
        if (Releases.DataSource != null)
        {
            try 
            {
                if (HttpContext.Current.Session["SelectedRelease" + this.ID] != null)
                {
                    Releases.SelectedValue = HttpContext.Current.Session["SelectedRelease" + this.ID].ToString();
                }
                else 
                {
                    StringDictionary settings = GetSettings();
                    if (settings.ContainsKey("SelectedRelease"))
                    {
                        Releases.SelectedValue = settings["SelectedRelease"];
                    }
                    else
                    {
                        Releases.SelectedIndex = 0;       
                    }
                }
            }
            catch (ArgumentOutOfRangeException e)
            {
                Releases.SelectedIndex = -1;
            }
            Node_Populate(new Object(), new TreeNodeEventArgs(new TreeNode()));
        }
        treeData.Visible = true;
    }

    /// <summary>
    /// Shows the edit.
    /// </summary>
    public override void ShowEdit()
    {
        DivEdit.Visible = true;
    }

    /// <summary>
    /// Hides the edit.
    /// </summary>
    public override void HideEdit()
    {
        DivEdit.Visible = false;
    }
    
    /// <summary>
    /// SAve widget settings
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.Web.UI.WebControls.GridViewPageEventArgs"/> instance containing the event data.</param>
    protected void LinkButtonSave_Click(object sender, EventArgs e)
    {
        //save config
    }

    /// <summary>
    /// Populates node of the tree
    /// </summary>
    /// <param name="sender">Sender</param>
    /// <param name="e">Node of the tree</param>
    protected void Node_Populate(object sender, TreeNodeEventArgs e)
    {
        {
            if (e.Node.ChildNodes.Count == 0)
            {
                switch (e.Node.Depth)
                {
                    case 0:
                        fillSprints(e.Node);
                        treeData.ExpandAll();
                        break;
                    case 1:
                        fillUserStoriesForSprint(e.Node);
                        break;
                    case 2:
                        fillBliForUserStory(e.Node);
                        break;
                    case 3:
                        fillTasksForBli(e.Node);
                        break;
                }
            }
        }
    }

    /// <summary>
    /// Adds subnodes defining all the sprints for the node
    /// </summary>
    /// <param name="node">Parent node</param>
    private void fillSprints(TreeNode node)
    {
        if (Releases.SelectedIndex != -1)
        {
            TreeNode tn = new TreeNode("Sprints");
            treeData.Nodes.Clear();
            treeData.Nodes.Add(tn);
            foreach (Sprint row in DAOSprint.GetAllSprintsForRelease(System.Convert.ToInt32(Releases.SelectedValue)))
            {
                createSubNode(tn, row.Name, row.ID.ToString(), (string)GetLocalResourceObject("Sprint"));
            }
        }
    }

    /// <summary>
    /// Adds subnodes defining all the userstories for the node that represents sprint
    /// </summary>
    /// <param name="node">Parent node</param>
    private void fillUserStoriesForSprint(TreeNode node)
    {
        string sprintID = node.Value;

        IList<UserStory> userStories = DAOUserStory.GetAllUserStoriesForSprint(System.Convert.ToInt32(sprintID));
        foreach (UserStory row in userStories)
        {
            createSubNode(node, row.Name, row.ID.ToString(), (string)GetLocalResourceObject("US"));
        }
    }

    /// <summary>
    /// Adds subnodes defining all the blis for the node that represents user story
    /// </summary>
    /// <param name="node">Parent node</param>
    private void fillBliForUserStory(TreeNode node)
    {
        string usID = node.Value;

        IList<BLI> blis = DAOBli.GetAllBlisForUserStory(System.Convert.ToInt32(usID));
        foreach (BLI row in blis)
        {
            createSubNode(node, row.Name, row.ID.ToString(), (string)GetLocalResourceObject("BLI"));
        }
    }

    /// <summary>
    /// Adds subnodes defining all the Tasks for the node that represents bli
    /// </summary>
    /// <param name="node">Parent node</param>
    private void fillTasksForBli(TreeNode node)
    {
        int bliID = System.Convert.ToInt32(node.Value);
        IList<Task> tasks = DAOTask.GetAllTasksForBli(DAOBli.GetBliByID(bliID));
        foreach (Task row in tasks)
        {
            createSubNode(node, row.Name, row.ID.ToString(), (string)GetLocalResourceObject("Task"));
        }
    }

    /// <summary>
    /// Creates new subnode
    /// </summary>
    /// <param name="parent">Parent node</param>
    /// <param name="name">Name of new subnode</param>
    /// <param name="id">Value that represents new node</param>
    /// <returns>New node</returns>
    private TreeNode createSubNode(TreeNode parent, String name, String id, string type)
    {
        TreeNode newNode = new TreeNode(name, id);
        newNode.PopulateOnDemand = true;
        newNode.SelectAction = TreeNodeSelectAction.Select;
        newNode.ToolTip = type;
        parent.ChildNodes.Add(newNode);
        return newNode;
    }

    /// <summary>
    /// Handle click on data in tree and shows details
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.Web.UI.WebControls.GridViewPageEventArgs"/> instance containing the event data.</param>
    protected void treeData_SelectedNodeChanged(object sender, EventArgs e)
    {
        if (treeData.SelectedNode == null)
        {
            return;
        }
        hideDetails();
        AddNewBtn.Visible = true;
        switch (treeData.SelectedNode.Depth)
        {
            case 0:
                {
                    AddNewBtn.Text = (string)GetLocalResourceObject("AddSprint");
                    OkDiv.Visible = false;
                    return;
                }
            case 1:
                {
                    AddNewBtn.Text = (string)GetLocalResourceObject("AddUserStory");
                    Sprint spr = DAOSprint.GetSprintById(System.Convert.ToInt32(treeData.SelectedNode.Value));
                    Release re = DAORelease.GetReleaseById(System.Convert.ToInt32(Releases.SelectedValue));
                    IList<Release> reles = DAORelease.GetAllReleasesForProject(re.Project.ID);
                    SprintDetails.SuperiorItemID = re.ID;
                    SprintDetails.AvailableSuperiorItems = reles;
                    SprintDetails.DisplayItem(spr);
                    break;
                }
            case 2:
                {
                    AddNewBtn.Text = (string)GetLocalResourceObject("AddBli");
                    UserStory usrStry = DAOUserStory.GetUserStoryByID(System.Convert.ToInt32(treeData.SelectedNode.Value));
                    //UserStoryDetails.AvailableSuperiorItems = DAOSprint.GetAllSprintsForRelease(System.Convert.ToInt32(Releases.SelectedValue));
                    // TODO : pozriet sa na TreeViewWidget
                    UserStoryDetails.SuperiorItemID = System.Convert.ToInt32(treeData.SelectedNode.Parent.Value);
                    UserStoryDetails.DisplayItem(usrStry);
                    break;
                }
            case 3:
                {
                    AddNewBtn.Text = (string)GetLocalResourceObject("AddTask");
                    BLI bli = DAOBli.GetBliByID(System.Convert.ToInt32(treeData.SelectedNode.Value));
                    UserStory us = DAOUserStory.GetUserStoryByBliID(System.Convert.ToInt32(treeData.SelectedNode.Value));
                    IList<UserStory> uss = DAOUserStory.GetAllUserStoriesForSprint(System.Convert.ToInt32(treeData.SelectedNode.Parent.Parent.Value));
                    BliDetails.SuperiorItemID = us.ID;
                    BliDetails.AvailableSuperiorItems = uss;
                    BliDetails.DisplayItem(bli);
                    break;
                }
            case 4:
                {
                    Task tsk = DAOTask.GetTaskByID(System.Convert.ToInt32(treeData.SelectedNode.Value));
                    IList<BLI> blis = DAOBli.GetAllBlisForUserStory(System.Convert.ToInt32(treeData.SelectedNode.Parent.Parent.Value));
                    TaskDetails.AvailableSuperiorItems = blis;
                    TaskDetails.DisplayItem(tsk);
                    TaskDetails.DetailedTask = tsk;
                    AddNewBtn.Visible = false;
                    break;
                }
            default:
                return;
        }
        OkDiv.Visible = true;
        CreateBtn.Visible = false;
        EditBtn.Visible = true;
        DeleteBtn.Visible = true;
    }

    /// <summary>
    /// Creates new entity
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.Web.UI.WebControls.GridViewPageEventArgs"/> instance containing the event data.</param>
    protected void AddNewSubEntityBtn_Click(object sender, EventArgs e)
    {
        if (treeData.SelectedNode == null)
        {
            return;
        }
        hideDetails();
        AddNewBtn.Visible = true;
        switch (treeData.SelectedNode.Depth)
        {
            case 0:
                {
                    AddNewBtn.Text = (string)GetLocalResourceObject("AddUserStory");
                    Release re = DAORelease.GetReleaseById(System.Convert.ToInt32(Releases.SelectedValue));
                    IList<Release> reles = DAORelease.GetAllReleasesForProject(re.Project.ID);
                    SprintDetails.SuperiorItemID = re.ID;
                    SprintDetails.AvailableSuperiorItems = reles;
                    SprintDetails.SelectedItem = null;
                    break;
                }
            case 1:
                {
                    AddNewBtn.Text = (string)GetLocalResourceObject("AddBli");
                    UserStoryDetails.SuperiorItemID = System.Convert.ToInt32(treeData.SelectedNode.Value);
                    //UserStoryDetails.AvailableSuperiorItems = DAOSprint.GetAllSprintsForRelease(System.Convert.ToInt32(Releases.SelectedValue));
                    // TODO : pozriet sa na TreeViewWidget
                    UserStoryDetails.SelectedItem = null;
                    break;
                }
            case 2:
                {
                    AddNewBtn.Text = (string)GetLocalResourceObject("AddTask");
                    IList<UserStory> uss = DAOUserStory.GetAllUserStoriesForSprint(System.Convert.ToInt32(treeData.SelectedNode.Parent.Value));
                    BliDetails.SuperiorItemID = System.Convert.ToInt32(treeData.SelectedNode.Value);
                    BliDetails.AvailableSuperiorItems = uss;
                    BliDetails.SelectedItem = null;
                    break;
                }
            case 3:
                {
                    IList<BLI> blis = DAOBli.GetAllBlisForUserStory(System.Convert.ToInt32(treeData.SelectedNode.Parent.Value));
                    TaskDetails.AvailableSuperiorItems = blis;
                    TaskDetails.SuperiorItemID = System.Convert.ToInt32(treeData.SelectedNode.Value);
                    TaskDetails.SelectedItem = null;
                    AddNewBtn.Visible = false;
                    break;
                }
            default:
                {
                    return;
                }
        }
        AddNewBtn.Visible = false;
        OkDiv.Visible = true;
        CreateBtn.Visible = true;
        EditBtn.Visible = false;
        DeleteBtn.Visible = false;
    }

    /// <summary>
    /// Sets visibility of all detail panels to false
    /// </summary>
    private void hideDetails()
    {
        UserStoryDetails.Visible = false;
        BliDetails.Visible = false;
        TaskDetails.Visible = false;
        SprintDetails.Visible = false;
        OkDiv.Visible = false;
    }

    /// <summary>
    /// Creates new entity
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.Web.UI.WebControls.GridViewPageEventArgs"/> instance containing the event data.</param>
    protected void CreateBtn_Click1(object sender, EventArgs e)
    {
        if (treeData.SelectedNode == null)
        {
            return;
        }
        TreeNode n;
        switch (treeData.SelectedNode.Depth)
        {
            case 3:
                {
                    Task tsk = TaskDetails.CreateItem();
                    n = createSubNode(treeData.SelectedNode, tsk.Name, tsk.ID.ToString(), (string)GetLocalResourceObject("Task"));
                    break;
                }
            case 2:
                {
                    BLI bli = BliDetails.CreateItem();
                    n = createSubNode(treeData.SelectedNode, bli.Name, bli.ID.ToString(), (string)GetLocalResourceObject("BLI"));
                    break;
                }
            case 1:
                {
                    UserStory us = UserStoryDetails.CreateItem();
                    n = createSubNode(treeData.SelectedNode, us.Name, us.ID.ToString(), (string)GetLocalResourceObject("US"));
                    break;
                }
            case 0:
                {
                    Sprint spr = SprintDetails.CreateItem();
                    n = createSubNode(treeData.SelectedNode, spr.Name, spr.ID.ToString(), (string)GetLocalResourceObject("Sprint"));
                    break;
                }
            default:
                {
                    return;
                }
        }
        treeData.DataBind();
        if (n != null)
        {
            n.Select();
            treeData_SelectedNodeChanged(new Object(), new EventArgs());
        }
    }

    /// <summary>
    /// Cancel event 
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.Web.UI.WebControls.GridViewPageEventArgs"/> instance containing the event data.</param>
    protected void CancelBtn_Click(object sender, EventArgs e)
    {
        hideDetails();
        //treeData_SelectedNodeChanged(new Object(), new EventArgs());
    }

    /// <summary>
    /// Delete event 
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.Web.UI.WebControls.GridViewPageEventArgs"/> instance containing the event data.</param>
    protected void DeleteBtn_Click(object sender, EventArgs e)
    {
        if (treeData.SelectedNode == null)
        {
            return;
        }
        switch (treeData.SelectedNode.Depth)
        {
            case 4:
                {
                    int taskID = System.Convert.ToInt32(treeData.SelectedNode.Value);
                    TaskDetails.DeleteItem(DAOTask.GetTaskByID(taskID));
                    break;
                }
            case 3:
                {
                    int bliID = System.Convert.ToInt32(treeData.SelectedNode.Value);
                    BliDetails.DeleteItem(DAOBli.GetBliByID(bliID));
                    break;
                }
            case 2:
                {
                    
                    int usID = System.Convert.ToInt32(treeData.SelectedNode.Value);
                    UserStoryDetails.DeleteItem(DAOUserStory.GetUserStoryByID(usID));
                    break;
                }
            case 1:
                {
                    int sprID = System.Convert.ToInt32(treeData.SelectedNode.Value);
                    SprintDetails.DeleteItem(DAOSprint.GetSprintById(sprID));
                    return;
                }
            case 0:
                {
                    return;
                }
            default:
                {
                    return;
                }
        }
        TreeNode node = treeData.SelectedNode.Parent;
        TreeNode toSelectNext;
        node.ChildNodes.Remove(treeData.SelectedNode);
        if (node.ChildNodes.Count == 0)
        {
            toSelectNext = node;
        }
        else
        {
            toSelectNext = node.ChildNodes[0];
        }
        treeData.DataBind();
        if (toSelectNext != null)
        {
            toSelectNext.Select();
            treeData_SelectedNodeChanged(new Object(), new EventArgs());
        }
    }

    /// <summary>
    /// Edit event on the node
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.Web.UI.WebControls.GridViewPageEventArgs"/> instance containing the event data.</param>
    protected void EditBtn_Click(object sender, EventArgs e)
    {
        if (treeData.SelectedNode == null)
        {
            return;
        }
        switch (treeData.SelectedNode.Depth)
        {
            case 4:
                {
                    Task tsk = TaskDetails.EditItem(System.Convert.ToInt32(treeData.SelectedNode.Value));
                    TreeNode node = editTree(tsk.BacklogItem.ID);
                    node.Text = tsk.Name;
                    node.Select();
                    break;
                }
            case 3:
                {
                    BLI bli = BliDetails.EditItem(System.Convert.ToInt32(treeData.SelectedNode.Value));
                    TreeNode node = editTree(BliDetails.SuperiorItemID);
                    node.Text = bli.Name;
                    node.Select();
                    break;
                }
            case 2:
                {
                    UserStory us = UserStoryDetails.EditItem(System.Convert.ToInt32(treeData.SelectedNode.Value));
                    TreeNode node = editTree(UserStoryDetails.SuperiorItemID);
                    node.Text = us.Name;
                    node.Select();
                    break;
                }
            case 1:
                {
                    Sprint spr = SprintDetails.EditItem(System.Convert.ToInt32(treeData.SelectedNode.Value));
                    TreeNode node = editTree(SprintDetails.GetInRelease());
                    node.Text = spr.Name;
                    node.Select();
                    break;
                }
            default:
                {
                    return;
                }
        }
        treeData.DataBind();
        treeData_SelectedNodeChanged(new Object(), new EventArgs());
    }

    /// <summary>
    /// Edits the tree 
    /// </summary>
    /// <param name="newParentNodeId">Id of Parent node</param>
    /// <returns>Edited node</returns>
    private TreeNode editTree(int newParentNodeId)
    {
        TreeNode node = treeData.SelectedNode;
        TreeNode parent = treeData.SelectedNode.Parent;
        parent.ChildNodes.Remove(node);
        bool found = false;
        foreach (TreeNode t in parent.Parent.ChildNodes)
        {
            if (!found && t.Value.Equals(newParentNodeId.ToString()))
            {
                t.ChildNodes.Add(node);
                found = true;
            }
        }
        return node;
    }

    /// <summary>
    /// HAndler for selection of release chxange
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.Web.UI.WebControls.GridViewPageEventArgs"/> instance containing the event data.</param>
    protected void Releases_SelectedIndexChanged(object sender, EventArgs e)
    {
        HttpContext.Current.Session["SelectedRelease" + this.ID] = Releases.SelectedValue;
        Node_Populate(new Object(), new TreeNodeEventArgs(new TreeNode()));
        Widget widget = DAOWidget.GetWidgetByID(this.ID);
        DAOWidgetSettings.SaveCreateSettings(widget, "SelectedRelease", Releases.SelectedValue);
        hideDetails();
    }
}
